package com.ky.manage.utils.threadpool;

import android.content.Context;
import android.text.TextUtils;

import com.ky.manage.BaseApplication;
import com.ky.manage.constant.OverallData;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import cn.ycbjie.ycthreadpoollib.PoolThread;
import cn.ycbjie.ycthreadpoollib.callback.AsyncCallback;
import cn.ycbjie.ycthreadpoollib.callback.ThreadCallback;
import cn.ycbjie.ycthreadpoollib.deliver.AndroidDeliver;

/**
 * 线程池工具类
 *
 * @author zhaoyan
 * @date 2019-12-06
 */
public class ThreadPoolUtils {
    private static final int DEFAULT_THREAD_CNT = 25;
    private static volatile ThreadPoolUtils threadPoolInstance;
    private Context mContext;
    //可用并发数的线程池，超过并发数的线程，在队列里面等待
    private PoolThread mFixedCorePoolThread, mCachedPoolThread;

    private ThreadPoolUtils() {
        mContext = BaseApplication.getContext();
        initFixedThreadPool();
        initCachedThreadPool();
    }

    public static ThreadPoolUtils getInstance() {
        if (threadPoolInstance == null) {
            synchronized (ThreadPoolUtils.class) {
                if (threadPoolInstance == null) {
                    threadPoolInstance = new ThreadPoolUtils();
                }
            }
        }
        return threadPoolInstance;
    }

    /**
     * 初始化线程池管理器
     */
    private void initFixedThreadPool() {
        if (null != mFixedCorePoolThread) {
            return;
        }
        // 创建一个独立的实例进行使用
        //可用并发数的线程池，超过并发数的线程，在队列里面等待
        //当前项目偏CPU任务多
        int CPU_COUNT = Runtime.getRuntime().availableProcessors();
        //线程数量固定的线程池，全部为核心线程，响应较快，不用担心线程会被回收
        mFixedCorePoolThread = PoolThread.ThreadBuilder
                .createFixed(Math.max(CPU_COUNT, DEFAULT_THREAD_CNT))
                .setPriority(Thread.MAX_PRIORITY)
                .setCallback(new LogCallback())
                .build();
    }

    /**
     * 初始化线程池管理器
     */
    private void initCachedThreadPool() {
        if (null != mCachedPoolThread) {
            return;
        }
        //它是一个数量无限多的线程池，都是非核心线程，适合执行大量耗时小的任务
        mCachedPoolThread = PoolThread.ThreadBuilder
                .createCacheable()
                .setPriority(Thread.NORM_PRIORITY)
                .setCallback(new LogCallback())
                .build();
    }

    /**
     * 获取线程池管理器对象，统一的管理器维护所有的线程池
     *
     * @return executor对象
     */
    public PoolThread getFixedPoolThread() {
        initFixedThreadPool();
        return mFixedCorePoolThread;
    }

    /**
     * 获取线程池管理器对象，统一的管理器维护所有的线程池
     *
     * @return executor对象
     */
    public PoolThread getCachedPoolThread() {
        initCachedThreadPool();
        return mCachedPoolThread;
    }

    /**
     * 最简单的线程调用方式：核心线程
     *
     * @param threadName
     * @param delaySeconds
     * @param runnable
     * @param callback
     */
    public void executeCoreJob(String threadName, long delaySeconds, Runnable runnable, ThreadCallback callback) {
        if (TextUtils.isEmpty(threadName) || null == runnable) {
            return;
        }
        initFixedThreadPool();
        mFixedCorePoolThread.setName(OverallData.THREAD_START_TAG + threadName);
        if (delaySeconds > 0) {
            mFixedCorePoolThread.setDelay(delaySeconds, TimeUnit.SECONDS);
        }
        mFixedCorePoolThread.setDeliver(new AndroidDeliver());
        if (null != callback) {
            mFixedCorePoolThread.setCallback(callback);
        }
        //启动任务, 在将来的某个时间执行给定的命令
        mFixedCorePoolThread.execute(runnable);
    }

    /**
     * 最简单的线程调用方式
     *
     * @param threadName
     * @param delaySeconds
     * @param runnable
     * @param callback
     */
    public void executeNormalJob(String threadName, long delaySeconds, Runnable runnable, ThreadCallback callback) {
        if (TextUtils.isEmpty(threadName) || null == runnable) {
            return;
        }
        initCachedThreadPool();
        mCachedPoolThread.setName(OverallData.THREAD_START_TAG + threadName);
        if (delaySeconds > 0) {
            mCachedPoolThread.setDelay(delaySeconds, TimeUnit.SECONDS);
        }
        mCachedPoolThread.setDeliver(new AndroidDeliver());
        if (null != callback) {
            mCachedPoolThread.setCallback(callback);
        }
        //启动任务, 在将来的某个时间执行给定的命令
        mCachedPoolThread.execute(runnable);
    }

    /**
     * 异步回调:核心线程
     *
     * @param threadName
     * @param delaySeconds
     * @param callable
     * @param callback
     */
    public <T> void executeSyncCoreJob(String threadName, long delaySeconds, Callable<T> callable, AsyncCallback<T> callback) {
        if (TextUtils.isEmpty(threadName) || null == callable) {
            return;
        }
        initFixedThreadPool();
        mFixedCorePoolThread.setName(OverallData.THREAD_START_TAG + threadName);
        if (delaySeconds > 0) {
            mFixedCorePoolThread.setDelay(delaySeconds, TimeUnit.SECONDS);
        }
        // 启动异步任务，回调用于接收可调用任务的结果
        mFixedCorePoolThread.async(callable, callback);
    }

    /**
     * 异步回调
     *
     * @param threadName
     * @param delaySeconds
     * @param callable
     * @param callback
     */
    public <T> void executeSyncNormalJob(String threadName, long delaySeconds, Callable<T> callable, AsyncCallback<T> callback) {
        if (TextUtils.isEmpty(threadName) || null == callable) {
            return;
        }
        initCachedThreadPool();
        mCachedPoolThread.setName(OverallData.THREAD_START_TAG + threadName);
        if (delaySeconds > 0) {
            mCachedPoolThread.setDelay(delaySeconds, TimeUnit.SECONDS);
        }
        // 启动异步任务，回调用于接收可调用任务的结果
        mCachedPoolThread.async(callable, callback);
    }
}
